<?php
// +----------------------------------------------------------------------
// | INPHP
// +----------------------------------------------------------------------
// | Copyright (c) 2021 https://inphp.cc All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/MIT )
// +----------------------------------------------------------------------
// | Author: lulanyin <me@lanyin.lu>
// +----------------------------------------------------------------------
// |
// |                          redis 缓存
// |
// +----------------------------------------------------------------------
namespace Inphp\Redis;

use Inphp\App;
use Inphp\Config;
use Inphp\Util\File;

class Redis
{
    /**
     * 连接配置
     * @var array
     */
    private static array $config = [];

    /**
     * redis连接池
     * @var Connection|null
     */
    private static Connection|null $connection = null;

    /**
     * 获取Redis连接对象
     * @return \Redis
     */
    public static function getConnection(): \Redis
    {
        if(is_null(self::$connection))
        {
            if(empty(self::$config))
            {
                self::$config = Config::get("service.redis") ?? [];
            }
            self::$connection = new Connection(self::$config);
        }
        if(App::isSwoole())
        {
            return self::$connection->get();
        }
        else
        {
            return self::$connection->redis;
        }
    }

    /**
     * 保存
     * @param string $name
     * @param mixed $value
     * @param int $expire
     * @param string|null $name_prefix
     */
    public static function set(string $name, mixed $value, int $expire = 0, string|null $name_prefix = null)
    {
        $redis = self::getConnection();
        if($redis && $redis->isConnected())
        {
            //值处理
            $value = is_array($value) || is_object($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value;
            //过期时间
            $expire = $expire == 0 ? (self::$config['expire'] ?? 0) : $expire;
            $expire = is_numeric($expire) ? $expire : 0;
            if($expire > 0)
            {
                $redis->setex(self::getName($name, $name_prefix), $expire, $value);
            }
            else
            {
                $redis->set(self::getName($name, $name_prefix), $value);
            }
            //保存记录已经使用的键名
            $list = $redis->get(self::getName("tag_history", $name_prefix));
            $list = !empty($list) ? explode(",", $list) : [];
            if(!in_array($name, $list))
            {
                $list[] = $name;
                $redis->set(self::getName("tag_history", $name_prefix), join(",", $list));
            }
            //释放
            self::$connection->release($redis);
        }
        else
        {
            defined("RUNTIME") && File::writeEnd(RUNTIME."/log", "redis.txt", "由于redis未连接，无法保存数据，key: {$name}\r\nvalue: ".var_export($value)."\r\n");
        }
    }

    /**
     * 获取
     * @param string $name
     * @param mixed|null $default
     * @param string|null $name_prefix
     * @return mixed
     */
    public static function get(string $name, mixed $default = null, string|null $name_prefix = null): mixed
    {
        $redis = self::getConnection();
        if($redis && $redis->isConnected())
        {
            //
            $value = $redis->get(self::getName($name, $name_prefix));
            if(is_null($value))
            {
                return $default;
            }
            //释放
            self::$connection->release($redis);
            //值处理
            return json_decode($value, true) ?? $value;
        }
        else
        {
            defined("RUNTIME") && File::writeEnd(RUNTIME."/log", "redis.txt", "由于redis未连接，无法获取数据，key: {$name}\r\n");
        }
        return null;
    }

    /**
     * 移除
     * @param string $name
     * @param string|null $name_prefix
     * @return bool
     */
    public static function remove(string $name, string|null $name_prefix = null): bool
    {
        $redis = self::getConnection();
        if($redis && $redis->isConnected())
        {
            $result = $redis->del(self::getName($name, $name_prefix));
            //释放
            self::$connection->release($redis);
            //返回值
            return $result;
        }
        return true;
    }

    /**
     * 清除所有本系统涉及的缓存
     * @param string|null $name_prefix
     */
    public static function clean(string|null $name_prefix = null)
    {
        $list = self::get("tag_history");
        $list = !empty($list) ? explode(",", $list) : [];
        if(!empty($list))
        {
            $redis = self::getConnection();
            if($redis && $redis->isConnected())
            {
                foreach ($list as $name)
                {
                    $redis->del(self::getName($name, $name_prefix));
                }
                //释放回收连接
                self::$connection->release($redis);
            }
        }
    }

    /**
     * 处理缓存key名称
     * @param string $name
     * @param string|null $name_prefix
     * @return string
     */
    public static function getName(string $name, string|null $name_prefix = null): string
    {
        $prefix = self::$config['prefix'] ?? '';
        return (!empty($name_prefix) ? $name_prefix : $prefix).$name;
    }
}